package com.hjm.project.merPaid.merPaid.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hjm.common.exception.BusinessException;
import com.hjm.common.utils.LogUtils;
import com.hjm.common.utils.request.AutoLoadData;
import com.hjm.framework.cache.RedisUtils;
import com.hjm.framework.web.domain.AjaxResult;
import com.hjm.project.settleInfo.settleInfo.utils.ComeMoney;
import lombok.SneakyThrows;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.hjm.project.merPaid.merPaid.mapper.MerPaidMapper;
import com.hjm.project.merPaid.merPaid.domain.MerPaid;
import com.hjm.project.merPaid.merPaid.service.IMerPaidService;
import com.hjm.common.utils.text.Convert;
import org.springframework.transaction.annotation.Transactional;
import com.github.benmanes.caffeine.cache.Cache;

import javax.annotation.Resource;

/**
 * 打款数据Service业务层处理
 * 
 * @author LOVE
 * @date 2020-11-27
 */
@Service
public class MerPaidServiceImpl implements IMerPaidService 
{
    @Resource
    private MerPaidMapper merPaidMapper;

    @Resource
    Cache<String, Object> caffeineCache;
    @Resource
    @Qualifier(value = "newFixedThreadPool")
    private ExecutorService newFixedThreadPool;

    /**
     * 查询打款数据
     * 
     * @param id 打款数据ID
     * @return 打款数据
     */
    @Override
    public MerPaid selectMerPaidById(Long id)
    {
        return merPaidMapper.selectMerPaidById(id);
    }

    /**
     * 查询打款数据列表
     * 
     * @param merPaid 打款数据
     * @return 打款数据
     */
    @Override
    public List<MerPaid> selectMerPaidList(MerPaid merPaid)
    {
        return merPaidMapper.selectMerPaidList(merPaid);
    }

    /**
     * 新增打款数据
     * 
     * @param merPaid 打款数据
     * @return 结果
     */
    @Override
    public int insertMerPaid(MerPaid merPaid)
    {
        return merPaidMapper.insertMerPaid(merPaid);
    }

    /**
     * 修改打款数据
     * 
     * @param merPaid 打款数据
     * @return 结果
     */
    @Override
    @Transactional
    public int updateMerPaid(MerPaid merPaid)
    {
        return merPaidMapper.updateMerPaid(merPaid);
    }

    /**
     * 删除打款数据对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteMerPaidByIds(String ids)
    {
        return merPaidMapper.deleteMerPaidByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除打款数据信息
     * 
     * @param id 打款数据ID
     * @return 结果
     */
    @Override
    public int deleteMerPaidById(Long id)
    {
        return merPaidMapper.deleteMerPaidById(id);
    }

    /**
     * 未知重新查询
     * @Param [merPaid]
     * @Return int
     */
    @Override
    @Async
    public Integer queryUnknown(MerPaid merPaid){
        List<MerPaid> merPaids = new ArrayList<>();
        try {
            //获取所有未知出款信息
            merPaids = merPaidMapper.selectMerPaidList(merPaid);
            //发送未知查询
            if (CollectionUtils.isNotEmpty(merPaids)) {
                return 0;
            }

        } catch (Exception e){
            throw new BusinessException("queryUnknown：" + JSON.toJSONString(merPaids),e);
        }
        return 1;
    }


    /**
     * 出款失败重新出款
     * @Param [merPaid]
     * @Return int
     */
    @Override
    @Transactional
    public Integer errorAgain(MerPaid merPaid) {
        List<MerPaid> merPaids = new ArrayList<>();
        List<MerPaid> update = new ArrayList<>();
        LogUtils.logInfo("开始查询出款失败数据");
        try {
            //获取所有出款失败的信息
            //修改出款失败为 0-待处理
            merPaids = merPaidMapper.selectMerPaidList(merPaid);
            if (CollectionUtils.isNotEmpty(merPaids)) {
                LogUtils.logInfo("开始更新出款失败数据:" + JSONObject.toJSONString(merPaids));
                for (MerPaid paid : merPaids) {
                    MerPaid merPaid1 = new MerPaid();
                    merPaid1.setSettleState("0");
                    merPaid1.setSettleSerial(paid.getSettleSerial());
                    int i = merPaidMapper.updateMerPaidBatch(merPaid1);
                    if (i <= 0) {
                        LogUtils.logInfo("出款失败数据更新失败");
                        throw  new BusinessException("出款失败数据更新失败");
                    }
                }
            } else {
                LogUtils.logInfo("未查询到出款失败数据" + merPaids.size());
                return 0;
            }
        }catch (Exception e){
            throw new BusinessException("errorAgain：" + JSON.toJSONString(merPaids),e);
        }
        return 1;
    }


    @Override
    public AjaxResult reloadMoney(MerPaid merPaid) {
        List<MerPaid> merPaids = new ArrayList<>();
        LogUtils.logInfo("开始出款");
        RedisUtils redisUtils = RedisUtils.getInstance();
        String key = "sys_agent_mer_paid:";
        try {
            //获取所有待出款数据
            merPaids = merPaidMapper.selectMerPaidList(merPaid);
            if (CollectionUtils.isNotEmpty(merPaids)) {
                if (merPaids.size() > 20){
                    return AjaxResult.error("每次出款不得超过20条");
                }
                LogUtils.logInfo("出款数据:" + JSONObject.toJSONString(merPaids));
                for (MerPaid paid : merPaids) {
                     MerPaid cache = (MerPaid)redisUtils.getObj(key + paid.getSettleSerial());
                    if (cache != null) {
                       return AjaxResult.error("存在重复出款数据[" + paid.getSettleSerial() +"],出款处理中,每隔三分钟可出款一次");
                    } else {
                        redisUtils.set(key + paid.getSettleSerial(),paid,60L);
                    }
                    //TODO 清结算管理 > 结算信息 > 出款失败数据 > 发起出款
                    Map<String, String> body = ComeMoney.newOut(paid.getSettleSerial());
                    if (body == null || body.get("code").equals("300")) {
                        LogUtils.logInfo("出款失败::响应结果:" + paid.getSettleSerial() + "--" + body.get("msg"));
                        return AjaxResult.error("出款失败::响应结果:" + paid.getSettleSerial());
                    }
                }
            } else {
                LogUtils.logInfo("未查询到待处理数据" + merPaids.size());
                return AjaxResult.error("未查询到待处理数据");
            }
        }catch (Exception e){
            throw new BusinessException("errorAgain：" + JSON.toJSONString(merPaids),e);
        }
        return AjaxResult.success("出款成功");
    }

    /**
     * 商户出款失败重新出款
     * @Param [merPaid]
     * @Return int
     */
    @Override
    public AjaxResult merReloadMoney(MerPaid merPaid) {
        List<MerPaid> merPaids = new ArrayList<>();
        LogUtils.logInfo("开始出款");
        RedisUtils redisUtils = RedisUtils.getInstance();
        String key = "sys_mer_mer_paid:";
        try {
            //获取所有待出款数据
            merPaids = merPaidMapper.selectMerPaidList(merPaid);
            if (CollectionUtils.isNotEmpty(merPaids)) {
                if (merPaids.size() > 20){
                    return AjaxResult.error("每次出款不得超过20条");
                }
                LogUtils.logInfo("出款数据:" + JSONObject.toJSONString(merPaids));
                for (MerPaid paid : merPaids) {
                    MerPaid cache = (MerPaid)redisUtils.getObj(key + paid.getSettleSerial());
                    if (cache != null) {
                        return AjaxResult.error("存在重复出款数据[" + paid.getSettleSerial() +"],出款处理中,每隔三分钟可出款一次");
                    } else {
                        redisUtils.set(key + paid.getSettleSerial(),paid,60L);
                    }
                }

                List<MerPaid> finalMerPaids = merPaids;
                newFixedThreadPool.execute(new Runnable() {
                        @SneakyThrows
                        @Override
                        public void run() {
                            for (MerPaid paid : finalMerPaids) {
                                //TODO 清结算管理 > 结算信息 > 出款失败数据 > 发起出款
                                Map<String, String> body = ComeMoney.merPay(AutoLoadData.webMerRestartComeIp,AutoLoadData.webMerRestartComePort,paid.getSettleSerial());
                            }
                        }
                });
            } else {
                LogUtils.logInfo("未查询到待处理数据" + merPaids.size());
                return AjaxResult.error("未查询到待处理数据");
            }
        }catch (Exception e){
            throw new BusinessException("errorAgain：" + JSON.toJSONString(merPaids),e);
        }
        return AjaxResult.success("出款处理中,请稍后进行查询");
    }

    /**
     * 重试失败后的处理
     * @Param [e]
     * @Return int
     */
    /*@Log(title = "重试失败数据", businessType = BusinessType.UPDATE)
    public String result(BusinessException e) {
        String result = "";
        //查询未知3次后 又失败
        if (e.getMessage().indexOf("queryUnknown") > -1) {
            result = "查询3次未知数据异常" + e;
            LogUtils.logError("查询3次未知数据异常",e);
        }

        //重新出款三次失败
        if (e.getMessage().indexOf("errorAgain") > -1) {
            result = "发起重新出款失败数据异常" + e;
            LogUtils.logError("发起重新出款失败数据异常",e);
        }
        return result;
    }*/


}
